<?php

namespace App\Http\Controllers;

use App\Models\ScoreInfo;
use App\Models\ScoreLog;
use App\Models\UserAccountBorrow;
use App\Models\UserAccountBorrowLog;
use App\Models\UserInfo;
use App\Models\UserLibraryInfo;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 积分规则模块
 * Class ScoreRule
 * @package app\common\controller
 */
class ScoreRuleController
{
    public $model = null;
    public $scoreLogModel = null;
    public function __construct()
    {
        $this->model = new ScoreInfo();
        $this->scoreLogModel = new ScoreLog();
    }

    /**
     * 积分规则
     */
    public function lists()
    {
        $res = $this->model->select('id', 'type_name', 'score', 'number', 'intro')->where('is_open', 1)->where('is_del', 1)->get()->toArray();

        $controllerObj = new Controller();
        if ($res) {
            return $controllerObj->returnApi(200, '获取成功', true, $res);
        }
        return $controllerObj->returnApi(203, '暂无数据');
    }

    /**
     * 获取用户当前积分
     */
    public function getUserScore($user_id, $account_id = null)
    {
        $score_table = config('other.score_table');
        //优先使用读者证号
        if ($account_id && $score_table == 'user_account_lib') {
            $score = UserLibraryInfo::where('id', $account_id)->value('score');
            if (empty($score) && ($score !== 0 && $score !== '0')) {
                return '积分获取失败';
            }
            return (int)$score;
        }
        if (empty($user_id)) {
            return '积分获取失败';
        }

        $res = UserInfo::select('account_id', 'id', 'score')->where('id', $user_id)->first();
        if (empty($res)) {
            return '积分获取失败';
        }
        if ($score_table == 'user_info') {
            return (int)$res->score;
        }

        if (empty($res->account_id)) {
            return '未绑定读者证，请先绑定';
        }

        $score = UserLibraryInfo::where('id', $res->account_id)->value('score');
        if (empty($score) && ($score !== 0 && $score !== '0')) {
            return '积分获取失败';
        }
        return (int)$score;
    }

    /**
     * 设置用户当前积分
     */
    public function setUserScore($user_id, $account_id = null, $change_score = 0)
    {
        $score_table = config('other.score_table');
        //优先使用读者证号
        if ($score_table == 'user_account_lib') {
            if (empty($account_id)) {
                return '读者证号不能为空';
            }
            $account_info = UserLibraryInfo::where('id', $account_id)->first();
            if (empty($account_info)) {
                return '积分获取失败';
            }
            $score = $account_info->score + $change_score;

            if ($score < 0) {
                $change_score = $account_info->score; //原本积分就是扣除积分
                $change_score = -$change_score;
                $account_info->score = 0; //积分不能为负数
            } else {
                $account_info->score = $score;
            }
            $account_info->save();
            return $change_score; //返回本次扣除积分
        } else {
            if (empty($user_id)) {
                return '用户id不能为空';
            }
            $user_info = UserInfo::select('account_id', 'id', 'score')->where('id', $user_id)->first();
            if (empty($user_info)) {
                return '积分获取失败';
            }

            $score = $user_info->score + $change_score;
            if ($score < 0) {
                $change_score = $user_info->score; //原本积分就是扣除积分
                $change_score = -$change_score;
                $user_info->score = 0; //积分不能为负数
            } else {
                $user_info->score = $score;
            }
            $user_info->save();
            return $change_score; //返回本次扣除积分
        }
    }


    /**
     * 根据类型获取积分
     * @parma type
     */
    public function getScoreByType($type)
    {
        if (config('other.is_need_score')) {
            return $this->model->where('type', $type)->where('score', '<>', 0)->where('is_open', 1)->where('is_del', 1)->first();
        }
        return false; //如果不需要直接返回
    }



    /**
     * 判断积分状态，是否够操作
     */
    public function checkScoreStatus($type, $user_id = null, $account_id = null)
    {
        $score_info = $this->getScoreByType($type);

        if (!$score_info) {
            return ['code' => 201, 'msg' => '无效积分规则']; //没有规格，不操作
        }

        //不操作积分
        if (empty($score_info->score)) {
            return ['code' => 201, 'msg' => '无须操作积分']; //正常，不操作积分
        }

        $user_score = $this->getUserScore($user_id, $account_id);

        if (is_string($user_score)) {
            return ['code' => 202, 'msg' => $user_score]; //用户积分获取失败，报错
        }

        /**检查次数限制  注册和绑定不受限，都只能一次*/
        if ($score_info->number > 0 && !in_array($type, [1])) {
            $date = date("Y-m-d");
            $score_list = $this->scoreLogModel->where('account_id', $account_id)->where('type_id', $type)->where(function ($query) use ($date) {
                $query->whereRaw(DB::raw("DATE_FORMAT(`create_time`,'%Y-%m-%d') = '$date'"));
            })->pluck('score');
            $count = 0; //计算每天有效次数
            foreach ($score_list as $key => $val) {
                if ($score_info->score > 0) {
                    $count = $val > 0 ? $count + 1 : $count - 1;
                } else {
                    $count = $val > 0 ? $count - 1 : $count + 1;
                }
            }

            if ($count >= $score_info->number) {
                return ['code' => 201, 'msg' => '今天积分操作次数已满']; //正常，不操作积分
            }
        }
        $new_user_score =  $user_score + $score_info->score;

        if (!empty($new_user_score) && $new_user_score < 0) {
            return ['code' => 203, 'msg' => '积分不足，操作失败', 'user_score' => $user_score, 'score_info' => $score_info->toArray()]; //错误
        }

        return ['code' => 200, 'msg' => '', 'user_score' => $user_score, 'score_info' => $score_info->toArray()]; //正常，要操作积分
    }


    /**
     * 操作(修改)积分 除商品外
     */
    public function scoreChange($score_info, $user_id = null, $account_id = null, $system_id = 0, $time = null)
    {
        $user_score = $this->getUserScore($user_id, $account_id);

        if (is_string($user_score)) {
            return ['code' => 202, 'msg' => $user_score];
        }

        //修改用户积分
        $change_score = $this->setUserScore($user_id, $account_id, $score_info['score_info']['score']);
        /**记录积分log */
        $log_data = [
            'user_id' => $user_id,
            'account_id' => $account_id,
            'system_id' => $system_id,
            'score' => $change_score,
            'total_score' => $score_info['score_info']['score'],
            'type_id' => $score_info['score_info']['id'],
            'type' => $score_info['score_info']['type_name'],
            'intro' => $score_info['score_info']['intro'],
            'create_time' => $time ? $time : date("Y-m-d H:i:s")
        ];
        $this->addScoreLog($log_data);

        return ['code' => 200, 'msg' => '积分操作成功'];
    }

    /**
     * 积分退还 除商品外
     * @param $score 原本的积分  如果是减，这里就是正数，加就是负数
     */
    public function scoreReturn($type, $score, $user_id = null, $account_id = null, $intro = null, $system_id = 0, $title = '')
    {
        $score *= -1; //改变积分符号

        $score_table = config('other.score_table');
        //直接修改用户积分
        if ($score_table == 'user_account_lib') {
            $res = UserLibraryInfo::where('id', $account_id)->first();
        } else {
            $res = UserInfo::select('account_id', 'id', 'score')->where('id', $user_id)->first();
        }

        $res->score = $res->score + $score;
        $res->save();

        //获取积分规则
        $score_rule = $this->getScoreByType($type);
        /**记录积分log */
        $log_data = [
            'user_id' => $user_id,
            'account_id' => $account_id,
            'system_id' => $system_id,
            'score' => $score,
            'total_score' => $score,
            'type_id' => !empty($score_rule['id']) ? $score_rule['id'] : 0,
            'type' => !empty($title) ? $title : $score_rule['type_name'],
            'intro' => !empty($intro) ? $intro : '积分回退',
            'create_time' => date("Y-m-d H:i:s")
        ];

        $this->addScoreLog($log_data);

        return true;
    }

    /**
     * 商品、欠款缴纳积分扣除
     * @param $score 积分 如果是减，这里就是正数，加就是负数
     * @param $type_id 类型id  0 为商品   999 为缴纳欠款
     */
    public function scoreGoodChange($score, $user_id = null, $account_id = null, $type = null,  $type_id = 0, $system_id = 0, $msg = null)
    {
        $score *= -1; //改变积分符号

        $user_score = $this->getUserScore($user_id, $account_id);

        if (is_string($user_score)) {
            return ['code' => 202, 'msg' => $user_score];
        }

        if ($user_score + $score < 0) {
            return ['code' => 202, 'msg' => '积分不足，不允许兑换'];
        };

        //修改用户积分
        $change_score = $this->setUserScore($user_id, $account_id, $score);

        /**记录积分log */
        $log_data = [
            'user_id' => $user_id,
            'account_id' => $account_id,
            'system_id' => $system_id,
            'score' => $change_score,
            'total_score' => $score,
            'type_id' => $type_id,
            'type' => $type,
            'intro' => $msg,
            'create_time' => date("Y-m-d H:i:s")
        ];

        $this->addScoreLog($log_data);
    }

    /**
     * 商品积分返还
     * @param $score 原本的积分 不管正负
     */
    public function scoreGoodReturn($score, $user_id, $account_id, $type, $msg, $system_id)
    {
        $score_table = config('other.score_table');
        //直接修改用户积分
        if ($score_table == 'user_account_lib') {
            $res = UserLibraryInfo::where('id', $account_id)->first();
        } else {
            $res = UserInfo::select('account_id', 'id', 'score')->where('id', $user_id)->first();
        }
        $res->score = $res->score + $score;
        $res->save();

        /**记录积分log */
        $log_data = [
            'user_id' => $user_id,
            'account_id' => $account_id,
            'system_id' => $system_id,
            'score' => $score,
            'total_score' => $score,
            'type_id' => 0,
            'type' => $type,
            'intro' => $msg,
            'create_time' => date("Y-m-d H:i:s")
        ];

        $this->addScoreLog($log_data);
    }


    /**
     * 积分字样
     */
    public function getScoreMsg($score)
    {
        return $score > 0 ? '退回' : "返还";
    }


    /**
     * 添加积分信息
     * @parma $data
     */
    public function addScoreLog($data)
    {
        $scoreLogModel = new ScoreLog(); //重新初始化对象，避免多次调用，只成功一次
        $scoreLogModel->user_id = !empty($data['user_id']) ? $data['user_id'] : 0;
        $scoreLogModel->account_id = $data['account_id'] ?? 0;
        $scoreLogModel->system_id = !empty($data['system_id']) ? $data['system_id'] : 0; //系统消息id
        $scoreLogModel->score = $data['score'];
        $scoreLogModel->total_score = $data['total_score'];
        $scoreLogModel->type_id = $data['type_id'];
        $scoreLogModel->type = $data['type'];
        $scoreLogModel->intro = $data['intro'];
        $scoreLogModel->manage_id = !empty(request()->manage_id) ? request()->manage_id : 0;
        $scoreLogModel->create_time = !empty($data['create_time']) ? $data['create_time'] : date('Y-m-d H:i:s');

        $scoreLogModel->save();
    }


    /**
     * 获取用户积分信息，增加用户积分和扣除积分
     */
    public function getBorrowInfo($user_id, $account_id)
    {
        //判断积分系统是否开启
        if (!config('other.is_need_score')) {
            return false; //未设置积分规则
        }
        $score = ScoreInfo::whereIn('type', [9, 10, 11, 12])->where('is_open', 1)->where('is_del', 1)->first();
        if (empty($score)) {
            return false; //未设置积分规则
        }

        $start_time = "2021-01-01"; //开始计算时间，以前是从2020年开始的
        $start_year = date('Y', strtotime($start_time)); //开始年

        //获取今年借阅数据
        $now_year = date('Y');
        $now_start_time = date('Y') . '-01-01';
        $now_end_time = date('Y-m-d');

        if ($now_year >= $start_year && $start_time < $now_end_time) {
            $now_start_time = $now_year == $start_year ? $start_time : $now_start_time;
            $this->getBorrowScore($user_id, $account_id, $now_year, $now_start_time, $now_end_time);
        }
        //获取去年借阅数据
        $last_year = $now_year - 1;
        $last_start_time = $last_year . '-01-01';
        $last_end_time = $last_year . '-12-31';

        if ($last_year >= $start_year && $start_time < $last_end_time) {
            $last_start_time = $last_year == $start_year ? $start_time : $last_start_time;
            $this->getBorrowScore($user_id, $account_id, $last_year, $last_start_time, $last_end_time);
        }
    }

    /**
     * 根据具体借还数据，增减积分
     */
    public function getBorrowScore($user_id, $account_id, $year, $start_time, $end_time)
    {
        // $account_info = $this->getUserScore(null, $account_id);
        $account = UserLibraryInfo::where('id', $account_id)->value('account');
        $controllerObj = new Controller();
        $libApi = $controllerObj->getLibApiObj();
        $getLastBorrowInfo = $libApi->getReturnData($account, 1, 1000, $year, $start_time, $end_time, null, true);
        if (!empty($getLastBorrowInfo['code']) && $getLastBorrowInfo['code'] != 200) {
            return false; //代表无数据
        }
        $userBorrowNumberByYear = UserAccountBorrow::select('id', 'number')->where('account_id', $account_id)->where('year', $year)->first();

        $number = !empty($userBorrowNumberByYear['number']) ? $userBorrowNumberByYear['number'] : 0;
        if (count($getLastBorrowInfo['content']) <= $number) {
            return true; //表示已经添加完毕
        }
        // dump(!empty($userBorrowNumberByYear));
        if (!empty($userBorrowNumberByYear)) {
            $getLastBorrowInfo['content'] = array_splice($getLastBorrowInfo['content'], $number); //获取新增的项目
        }
        DB::beginTransaction();
        try {
            $userAccountBorrowLogModel = new UserAccountBorrowLog();

            //已经计算过的id
            $use_api_id = $userAccountBorrowLogModel->where('cardno', $account)->pluck('api_id')->toArray();

            foreach ($getLastBorrowInfo['content'] as $key => $val) {
                //判断此记录是否已经使用
                if (in_array($val['id'], $use_api_id)) {
                    continue;
                }

                $score_info = $this->getScoreInfo($val);
                if (empty($score_info)) {
                    return false; //不进行任何处理
                }
                $score_info['score_info'] = $score_info->toArray(); //统一数据格式
                //积分不够，直接减为负数
                // $score_status = $this->checkScoreStatus($score_info['type'], $account_id, true);
                // if ($score_status['code'] !== 200) {
                //     return false; //不进行任何处理
                // }

                //数据添加到数据表
                $userAccountBorrowLogModel->insert([
                    'api_id' => $val['id'],
                    'cardno' => $val['account'],
                    'title' => $val['book_name'],
                    'author' => $val['author'],
                    'isbn' => $val['isbn'],
                    'publish' => $val['press'],
                    'callno' => $val['book_num'],
                    'price' => $val['price'],
                    'barcode' => $val['barcode'],
                    'notes' => '借阅时间：' . $val['borrow_time'] . '；过期时间：' . $val['expire_time'],
                    'updateDateTime' => $val['return_time'],
                    'create_time' => date('Y-m-d H:i:s')
                ]);
                $change_time = $val['return_time'];
                $system_id = $controllerObj->systemAdd($score_info['score_info']['type_name'], $user_id, $account_id, 50, 0, $score_info['score_info']['intro'] . " ，书名为：《" . $val['book_name'] . '》', $change_time);
                $selfObj = new self();
                $selfObj->scoreChange($score_info, $user_id, $account_id, $system_id, $change_time); //添加积分消息

                /*//只返回已归还的记录
                if($val['eventType'] === 'Eg' || $val['eventType'] === 'Ec' || $val['eventType'] === 'Ed' || $val['eventType'] === 'Ef') {
                      ["id"] => int(5489913)
                      ["eventType"] => string(2) "Eg"
                      ["loginWay"] => string(8) "DLibsApi"
                      ["readerId"] => int(553044)
                      ["assetId"] => int(900755)
                      ["servrequestId"] => int(0)
                      ["metatable"] => string(9) "i_biblios"
                      ["metaid"] => int(685689)
                      ["curSublib"] => string(2) "BN"
                      ["curLocal"] => string(4) "BN_C"
                      ["initSublib"] => string(2) "BN"
                      ["initLocal"] => string(4) "BN_C"
                      ["cardno"] => string(14) "01131000999999"
                      ["readerLib"] => string(2) "BN"
                      ["realName"] => string(12) "测试读者"
                      ["barcode"] => string(14) "01079600000007"
                      ["cirType"] => string(3) "001"
                      ["volumeno"] => int(0)
                      ["title"] => string(21) "催眠师手记 . Ⅱ"
                      ["author"] => string(9) "高铭著"
                      ["isbn"] => string(17) "978-7-5502-9421-9"
                      ["publish"] => string(38) "北京:北京联合出版公司 , 2018"
                      ["callno"] => string(12) "R395.2/3/(2)"
                      ["price"] => string(8) "CNY48.00"
                      ["ip"] => string(9) "127.0.0.1"
                      ["notes"] => string(191) "还回！条码号：【01079600000007】，题名：催眠师手记 . Ⅱ，借出日期：2020-12-23 00:00:00，应还日期：2021-01-22 00:00:00，实际还回日期：2020-12-25 00:00:00"
                      ["adminName"] => string(12) "btkj_bxdd_yz"
                      ["updateDateTime"] => string(19) "2020-12-25 09:41:14"
                      ["eventTypeNote"] => string(18) "读者还回文献"
                      ["loginWayNote"] => string(20) "DLibsApi调用方式"
                      ["curSublibNote"] => string(24) "重庆市巴南图书馆"
                      ["curLocalNote"] => string(18) "总馆成人图书"
                      ["initSublibNote"] => string(24) "重庆市巴南图书馆"
                      ["initLocalNote"] => string(18) "总馆成人图书"
                      ["readerLibNote"] => string(24) "重庆市巴南图书馆"
                      ["cirTypeNote"] => string(18) "一卡通中文书"
                }*/
            }

            //修改次数
            if (empty($userBorrowNumberByYear)) {
                $userAccountBorrowModel = new UserAccountBorrow();
                $userAccountBorrowModel->account_id = $account_id;
                $userAccountBorrowModel->year = $year;
                $userAccountBorrowModel->number = count($getLastBorrowInfo['content']);
                $userAccountBorrowModel->save();
            } else {
                $userBorrowNumberByYear->number = count($getLastBorrowInfo['content']);
                $userBorrowNumberByYear->save();
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            dump($e->getMessage() . $e->getFile() . $e->getLine());
            die;
            DB::rollBack();
            return false;
        }
    }
    //BORROW("Ea", "读者借出"),
    /** 读者还回文献Eg */
    //  RETURN("Eg", "读者还回文献"),    //下面的枚举值，不能管什么情况，都会产生一条这个数据
    /** 读者续借Eb */
    // RENEW("Eb", "读者续借"),
    /** 读者过期Ec */
    //  OVERDUE("Ec", "读者过期"),
    /** 文献损坏Ed */
    //  DAMAGE("Ed", "文献损坏"),
    /** 读者丢失文献Ef */
    //  LOST("Ef", "读者丢失文献"),

    /**
     * 获取对应积分
     */
    public function _getScoreInfo($eventType)
    {
        switch ($eventType) {
            case 'Ea':
                $type = 8;
                break;
            case 'Eg':
                $type = 9;
                break;
            case 'Ec':
                $type = 10;
                break;
            case 'Ed':
                $type = 11;
                break;
            case 'Ef':
                $type = 12;
                break;
            default:
                return false;
        }
        $score = ScoreInfo::where('type', $type)->first();
        return $score;
    }

    /**
     * 获取对应积分
     */
    public function getScoreInfo($data)
    {
        if ($data['expire_time'] >= $data['return_time']) {
            $type = 9;
        } else {
            $type = 10;
        }
        $score = ScoreInfo::where('type', $type)->where('is_open', 1)->where('is_del', 1)->first();
        return $score;
    }
}
